package com.kepler.social.web.controller;

import com.kepler.social.common.constants.BusinessState;
import com.kepler.social.common.constants.TipsConst;
import com.kepler.social.common.exception.SystemException;
import com.kepler.social.common.utils.ValidateAssert;
import com.kepler.social.domain.support.media.MediaDomainService;
import com.kepler.social.web.common.HttpResult;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;
import java.util.UUID;

@RestController
@RequestMapping("/upload")
@Slf4j
public class UploadController {

    @Resource
    private MediaDomainService mediaDomainService;

    private Path tempDir = Paths.get(System.getProperty("java.io.tmpdir"));

    /**
     * 断点续传 分布式部署支持
     * 这个是基础功能，所以放入upload
     * 上传分片属于基础操作，对于前端而言，更愿意一个通用方法，而不是体现领域的多种方法，除非里边有对应的业务信息，比如对静态文件路径的定义等等。
     * 目前不考虑这种情况，所以还是放入一个路径。因为如果引用系统做得OK，那么就不会浪费。而且就算为了将来考虑，因为社区都是对应于个人，
     * 只要路径增加ID，那么处理用户相关文件也不会太慢。
     *
     * @param file        上传的文件
     * @param seqNo       请求的唯一ID
     * @param currentPart 当前块
     * @param totalPart   总块
     * @return
     */
    @PostMapping("/slice")
    @CrossOrigin
    public HttpResult sliceUpload(@RequestParam(name = "file") MultipartFile file, String seqNo, int currentPart, int totalPart) {
        log.info("sliceUpload fileName {} currentPart {} totalPart {}", file.getOriginalFilename(), currentPart, totalPart);
        ValidateAssert.isTrue(Objects.nonNull(file), TipsConst.param_absence + ":文件");
        ValidateAssert.isTrue(StringUtils.isNoneBlank(seqNo), TipsConst.param_absence + ":序列号");
        ValidateAssert.isTrue(currentPart >= 0, TipsConst.param_error + ":当前分片号");
        ValidateAssert.isTrue(totalPart > 0, TipsConst.param_error + ":总分片号");
        try (InputStream stream = file.getInputStream()) {
            mediaDomainService.uploadFileSlice(seqNo, stream, currentPart, totalPart);
        } catch (IOException e) {
            log.error("sliceUpload origin file seq {} fileName {} err {}", seqNo, file.getOriginalFilename(), e, e);
            throw new SystemException("文件系统异常");
        }
        return HttpResult.success();
    }

    /**
     * 断点续传，仅用来测试RandomAccessFile操作
     *
     * @param file
     * @return
     */
    @PostMapping("/slice/stand-alone")
    @CrossOrigin
    public HttpResult sliceUploadOnlyStandAlone(@RequestParam(name = "file") MultipartFile file) {
        Path tempFile = tempDir.resolve(file.getOriginalFilename());
        log.info(tempFile.toString());
        try (InputStream stream = file.getInputStream();
             RandomAccessFile ra = new RandomAccessFile(tempFile.toString(), "rw")) {
            ra.seek(ra.length());
            int bytesRead;
            int len = 1024;
            byte[] buffer = new byte[len];
            while ((bytesRead = stream.read(buffer, 0, len)) != -1) {
                ra.write(buffer, 0, bytesRead);
            }
        } catch (IOException ioEx) {
            return new HttpResult(BusinessState.SYS_ERROR.code, "文件系统IO异常");
        }
        return HttpResult.success(null);
    }


    /**
     * 上传视频进行切片处理，返回访问路径
     *
     * @param video
     * @return
     * @throws IOException
     */
    @PostMapping("/upload/whole-file")
    @CrossOrigin
    public HttpResult upload(@RequestParam(name = "file") MultipartFile video) throws IOException {
        /**    参数传UUID去数据库查询需要转换的视频地址 进行入参
         public ResponseData upload (@RequestParam("uuid") String uuid) throws Exception {
         TranscodeConfig transcodeConfig = new TranscodeConfig();
         FastDfsFile fastDfsFile = sectionService.getSectionByUUID(uuid);
         if(fastDfsFile.getFastDfsFileUrl() == null){
         LOGGER.info("请上传视频！！");
         return ResponseData.warnWithMsg("请选择要上传的视频！");
         }

         MultipartFile video = UrlToMultipartFile.urlToMultipartFile(fastDfsFile.getFastDfsFileUrl());
         */
        log.info("文件信息：title={}, size={}", video.getOriginalFilename(), video.getSize());

        // 原始文件名称，也就是视频的标题
        String title = video.getOriginalFilename();

        // io到临时文件
        Path tempFilePath = tempDir.resolve(title);
        log.info("io到临时文件：{}", tempFilePath);
        // 删除后缀
        title = title.substring(0, title.lastIndexOf(".")) + "-" + UUID.randomUUID().toString().replaceAll("-", "");
        video.transferTo(tempFilePath);
        return HttpResult.success(mediaDomainService.storeAsM3U8(title, tempFilePath));
    }

}
